#region Using directives

/*
 * Copyright (c) 2005-2007 Alan Dean.
 * All rights reserved.
 */

using System;
using System.Collections.Generic;
using System.Globalization;

using ObjectThinking.Globalization;
using ObjectThinking.Xml.ResourceDescriptionFramework;

#endregion

namespace ObjectThinking
{
    public sealed class MustBeOfTypeRule : RuleBase
    {
        private static readonly Uri ObjectKey = new Uri("urn:object-key");
        private static readonly Uri ObjectName = new Uri("urn:object-name");
        private static readonly Uri ObjectType = new Uri("urn:object-type");

        // public constructors

        public MustBeOfTypeRule(Uri key, string name)
            : this(key, name, null as Type)
        { }

        public MustBeOfTypeRule(Uri key, string name, Type type)
        {
            this[ObjectKey] = key;
            this[ObjectName] = name;
            this[ObjectType] = type;
        }

        // public methods (IRule)

        public override bool Validate(ISelf obj)
        {
            return Validate(obj, this[ObjectKey] as Uri, this[ObjectType] as Type);
        }

        // private methods

        public bool Validate(ISelf obj, Uri key, Type type)
        {
            if (obj == null) throw new ArgumentNullException();
            if (key == null) throw new ArgumentNullException();
            if (type == null) throw new ArgumentNullException();

            Rule.ClearViolations(this);

            object value = obj[key];

            if (value != null)
            {
                if (!(value is Type)) this[key] = new MustBeOfTypeViolation(this[ObjectName] as string, type);
            }

            return Rule.IsValid(this);
        }
    }
}